﻿#define EALLOW asm(" EALLOW")
#define EDIS   asm(" EDIS")
#define DINT   asm(" DINT")
#define EINT   asm(" EINT")
// TMS320F2812不支持ERTM指令，使用空定义替代
#define ERTM   asm(" nop")

// 系统控制寄存器
#define PLLCR      *((volatile unsigned int *) 0x7021) 
#define PCLKCR     *((volatile unsigned int *) 0x701C) // 外设时钟控制寄存器
#define HISPCP     *((volatile unsigned int *) 0x701A) // 高速外设时钟预分频器
#define LOSPCP     *((volatile unsigned int *) 0x701B) // 低速外设时钟预分频器
#define WDCR       *((volatile unsigned int *) 0x7029) // 看门狗控制寄存器
#define SCSR       *((volatile unsigned int *) 0x7022) // 系统控制状态寄存器

// GPIO寄存器
#define GPFMUX     *((volatile unsigned int *) 0x70D4) // GPIO F多路复用寄存器
#define GPFDIR     *((volatile unsigned int *) 0x70D5) // GPIO F方向寄存器
#define GPFDAT     *((volatile unsigned int *) 0x70F4) // GPIO F数据寄存器

// SCI-A寄存器
#define SCICCR     *((volatile unsigned int *) 0x7050) // SCI通信控制寄存器
#define SCICTL1    *((volatile unsigned int *) 0x7051) // SCI控制寄存器1
#define SCICTL2    *((volatile unsigned int *) 0x7052) // SCI控制寄存器2
#define SCIRXST    *((volatile unsigned int *) 0x7053) // SCI接收状态寄存器
#define SCIRXEMU   *((volatile unsigned int *) 0x7054) // SCI仿真数据缓冲寄存器
#define SCIRXBUF   *((volatile unsigned int *) 0x7055) // SCI接收数据缓冲寄存器
#define SCITXBUF   *((volatile unsigned int *) 0x7059) // SCI发送数据缓冲寄存器
#define SCIHBAUD   *((volatile unsigned int *) 0x7056) // SCI波特率高位寄存器
#define SCILBAUD   *((volatile unsigned int *) 0x7057) // SCI波特率低位寄存器
#define SCIFFTX    *((volatile unsigned int *) 0x705E) // SCI FIFO发送寄存器
#define SCIFFRX    *((volatile unsigned int *) 0x705F) // SCI FIFO接收寄存器
#define SCIFFCT    *((volatile unsigned int *) 0x7060) // SCI FIFO控制寄存器

// CPU定时器0寄存器
#define CpuTimer0Regs_TCR *((volatile unsigned int *) 0x0C00) // 定时器控制寄存器
#define CpuTimer0Regs_PRD *((volatile unsigned int *) 0x0C02) // 周期寄存器
#define CpuTimer0Regs_TPR *((volatile unsigned int *) 0x0C04) // 预分频寄存器
#define CpuTimer0Regs_TPRH *((volatile unsigned int *) 0x0C05) // 预分频高位寄存器

// 中断相关寄存器
#define IER        *((volatile unsigned int *) 0x00000000) // 中断使能寄存器
#define IFR        *((volatile unsigned int *) 0x00000001) // 中断标志寄存器
#define PIECTRL    *((volatile unsigned int *) 0x0CE0)     // PIE控制寄存器
#define PIEACK     *((volatile unsigned int *) 0x0CE1)     // PIE应答寄存器
#define PIEIER1    *((volatile unsigned int *) 0x0CE2)     // PIE中断使能寄存器1
#define PIEIFR1    *((volatile unsigned int *) 0x0CE3)     // PIE中断标志寄存器1
#define PIEIER9    *((volatile unsigned int *) 0x0CEA)     // PIE中断使能寄存器9
#define PIEIFR9    *((volatile unsigned int *) 0x0CF2)     // PIE中断标志寄存器9

// 宏定义
#define FIFO_SIZE       16U
#define LSPCLK_FREQ     18750000U     // 系统时钟为75MHz，低速外设时钟为18.75MHz
#define SCI_FREQ        115200U       // 波特率115200
#define SCI_PRD         ((LSPCLK_FREQ/(SCI_FREQ*8))-1) // 波特率计算

// 全局变量
unsigned int t_u16SendData[FIFO_SIZE] = {0};
unsigned int t_u16RcvData[FIFO_SIZE] = {0};
unsigned int u16Index = 0;
unsigned int bSendData = 0;

// 函数声明
void InitSysCtrl(void);
void InitGpio(void);
void InitPieCtrl(void);
void InitPieVectTable(void);
void InitSci(void);
void Scia_SendByte(unsigned char c);
void Scia_SendFifo(unsigned int *data, unsigned int size);
void ConfigCpuTimer(unsigned int period, unsigned int prescaler);

// 中断服务函数
interrupt void Scia_Rx_Fifo_ISR(void);
interrupt void Timer0_ISR(void);

// 关闭看门狗
void DisableDog(void)
{
    EALLOW;
    WDCR = 0x0068; // 关闭看门狗定时器
    EDIS;
}

// 初始化PLL
void InitPll(void)
{
    int i;
    EALLOW;
    PLLCR = 10; // SYSCLK = 外部时钟 * PLLCR /2
    EDIS;
    for(i = 0; i < ((131072/2)/12); i++) {;}
}

// 初始化外设时钟
void InitPeripheralClocks(void)
{
    EALLOW;
    HISPCP = 1;  // HISPCLK = SYSCLK/(2*HISPCP) = 75MHz/(2*1) = 37.5MHz
    LOSPCP = 2;  // LOSPCLK = SYSCLK/(2*LOSPCP) = 75MHz/(2*2) = 18.75MHz
    // 根据lab4的初始化，明确使能SCI-A时钟等外设时钟
    PCLKCR |= 0x0001; // EVAENCLK
    PCLKCR |= 0x0002; // EVBENCLK
    PCLKCR |= 0x0004; // SCIAENCLK (SCI-A时钟使能位)
    PCLKCR |= 0x0008; // SCIBENCLK
    PCLKCR |= 0x0010; // MCBSPENCLK
    PCLKCR |= 0x0020; // SPIENCLK
    PCLKCR |= 0x0040; // ECANENCLK
    EDIS;
}

// 初始化系统控制
void InitSysCtrl(void)
{
    DisableDog();
    InitPll();
    InitPeripheralClocks();
}

// 初始化GPIO
void InitGpio(void)
{
    EALLOW;
    // 配置SCIRXDA (GPIO28)和SCITXDA (GPIO29)
    // TMS320F2812的SCI-A引脚映射 - 使用直接寄存器操作
    GPFMUX |= 0x00C0;  // 设置GPIO29(F6)和GPIO28(F7)为SCI功能
    EDIS;
}

// 初始化SCI
void InitSci(void)
{
    // 复位SCI
    SCICTL1 = 0x0000;
    
    // 配置SCI通信参数
    SCICCR = 0x0007;  // 8位数据，无奇偶校验，1位停止位
    
    // 设置波特率
    SCIHBAUD = (SCI_PRD >> 8) & 0xFF;
    SCILBAUD = SCI_PRD & 0xFF;
    
    // 配置FIFO
    SCIFFTX = 0xC000;  // 使能FIFO (SCIFFENA=1)，复位SCI通道 (SCIRST=1)
    SCIFFRX = 0x2040;  // 设置接收FIFO中断级别为16 (RXFFIL=16)，使能FIFO中断 (RXFFIENA=1)
    SCIFFCT = 0x0000;  // FIFO控制寄存器，默认值
    
    // 使能SCI中断
    SCICTL2 |= 0x0003;  // 使能发送中断 (TXINTENA=1) 和接收中断 (RXBKINTENA=1)
    
    // 使能SCI
    SCICTL1 = 0x0023;  // 退出复位状态 (SWRESET=1)，使能接收 (RXENA=1) 和发送 (TXENA=1)
    
    // 清除SCIRST位，结束SCI通道复位
    SCIFFTX &= 0x7FFF;  // 清除SCIRST位 (bit15)
    
    // 复位FIFO
    SCIFFTX |= 0x0800;  // 复位发送FIFO (TXFIFOXRESET=1)
    SCIFFRX |= 0x0800;  // 复位接收FIFO (RXFIFORESET=1)
    
    // 清除FIFO复位位
    SCIFFTX &= 0xF7FF;  // 清除TXFIFOXRESET位 (bit13)
    SCIFFRX &= 0xF7FF;  // 清除RXFIFORESET位 (bit13)
}

// 发送单个字节
void Scia_SendByte(unsigned char c)
{
    while((SCIFFTX & 0x001F) != 0) {;}  // 检查发送FIFO状态
    SCITXBUF = c;
}

// 配置CPU定时器0
void ConfigCpuTimer(unsigned int period, unsigned int prescaler)
{
    CpuTimer0Regs_PRD = period - 1;
    CpuTimer0Regs_TPR = prescaler;
    CpuTimer0Regs_TPRH = prescaler >> 8;
    CpuTimer0Regs_TCR |= 0x0001;  // 重新加载定时器
}

// SCI接收中断服务函数
interrupt void Scia_Rx_Fifo_ISR(void)
{
    unsigned int i;
    
    // 读取接收到的数据
    for(i = 0; i < FIFO_SIZE; i++) {
        if(SCIRXST & 0x0001) {  // 检查是否有新数据
            t_u16RcvData[i] = SCIRXBUF & 0x00FF;
        } else {
            break;
        }
    }
    
    bSendData = 1;  // 设置发送标志
    
    // 清除溢出标志
    SCIFFRX |= 0x4000;  // 设置RXFFOVRCLR位 (bit14)
    
    // 清除中断标志
    SCIFFRX |= 0x0040;  // 设置RXFFINTCLR位 (bit6)
    
    // 应答中断 - 允许更多的组9中断
    PIEACK |= 0x0100;  // 设置PIEACK.9位
}

// 定时器0中断服务函数
interrupt void Timer0_ISR(void)
{
    // 清除定时器中断标志
    CpuTimer0Regs_TCR = 0xF000;  // 重新加载并清除中断标志
    
    // 如果收到数据，发送回数据
    if(bSendData) {
        for(u16Index = 0; u16Index < FIFO_SIZE; u16Index++) {
            if(t_u16RcvData[u16Index] != 0) {
                while((SCICTL2 & 0x0004) == 0) {;}  // 等待发送缓冲区为空
                SCITXBUF = t_u16RcvData[u16Index];
                t_u16RcvData[u16Index] = 0;  // 清除接收缓冲区
            }
        }
        bSendData = 0;
    }
    
    // 应答中断 - 允许更多的组1中断
    PIEACK |= 0x0001;  // 设置PIEACK.1位
}

// 主函数
void main(void)
{
    // 初始化系统控制
    InitSysCtrl();
    
    // 初始化GPIO（配置SCI引脚）
    InitGpio();
    
    // 禁用所有中断
    DINT;
    
    // 初始化PIE控制寄存器 - 禁用PIE模块
    EALLOW;
    PIECTRL &= 0xFFFFFFFE;  // 禁用PIE (PIECRTL.ENPIE = 0)
    
    // 清除PIE中断使能寄存器1和9（相关中断组）
    PIEIER1 = 0;  // PIEIER1
    PIEIER9 = 0;  // PIEIER9
    
    // 清除PIE中断标志寄存器1和9
    PIEIFR1 = 0;  // PIEIFR1
    PIEIFR9 = 0;  // PIEIFR9
    EDIS;
    
    // 清除CPU中断标志
    IFR = 0x00000000;
    IER = 0x00000000;
    
    // 初始化SCI
    InitSci();
    
    // 配置定时器0，用于数据回传处理
    ConfigCpuTimer(75000, 0);  // 75MHz系统时钟，75000个周期为1ms
    
    // 使能中断 - 设置向量表
    EALLOW;
    // SCI接收中断向量地址
    *(volatile void **)0x0D98 = &Scia_Rx_Fifo_ISR;  // SCIRXINTA向量
    // 定时器0中断向量地址
    *(volatile void **)0x0D4C = &Timer0_ISR;  // TINT0向量
    EDIS;
    
    // 使能特定中断
    EALLOW;
    PIEIER9 |= 0x0001;  // 使能PIEIER9.INTx1 (SCI接收中断)
    PIEIER1 |= 0x0080;  // 使能PIEIER1.INTx7 (定时器0中断)
    EDIS;
    
    // 使能PIE和全局中断
    EALLOW;
    PIECTRL |= 0x0001;  // 启用PIE (PIECRTL.ENPIE = 1)
    PIEACK = 0xFFFF;    // 清除所有PIEACK
    EDIS;
    
    IER |= 0x0001;  // 使能INT1
    IER |= 0x0100;  // 使能INT9
    EINT;
    // 移除ERTM指令，TMS320F2812不支持
    
    // 主循环
    while(1) {
        // 主循环保持空闲
    }
}
